package com.vincent.jvmtest.httpclient;

import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.EntityBuilder;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.ssl.TrustStrategy;

import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class HttpsTest {
    private static CloseableHttpClient client = null;					// HTTP客户端

    public static void main(String agrs[]) throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {

        initHttpClient();
        HttpPost httpPost = new HttpPost("https://127.0.0.1:8443/hello/test");
        HttpEntity entity = EntityBuilder.create()
                .setContentType(ContentType.APPLICATION_JSON)
                .setContentEncoding("UTF-8")
                .setBinary("REQ".getBytes())//填写请求消息
                .build();


        try {
            CloseableHttpResponse resp = client.execute(httpPost);
            InputStream input = resp.getEntity().getContent();
            long l = resp.getEntity().getContentLength();//   ("content-length");
            byte b[] = new byte[1024];
            input.read(b);
            input.close();
            System.out.println("resp:"+(new String(b)));
            resp.close();
        } catch (Exception e) {
            //System.out.println(reqId);
            e.printStackTrace();
        }


    }



    public static void initHttpClient() throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException	{
        SSLContext ctx = SSLContexts.custom()
                .loadTrustMaterial(null, new TrustStrategy() {
                    @Override
                    public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                        return true;		// 信任所有证书
                    }
                })
                .build();
        SSLConnectionSocketFactory sslsf = null;// = new SSLConnectionSocketFactory(ctx, NoopHostnameVerifier.INSTANCE);
        try {
            sslsf = getSSLConnectsf();  //认证
            //sslsf = new SSLConnectionSocketFactory(ctx, NoopHostnameVerifier.INSTANCE); //忽略
        } catch (Exception e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        Registry<ConnectionSocketFactory> sfr = RegistryBuilder.<ConnectionSocketFactory> create()
                .register("http", new PlainConnectionSocketFactory())
                .register("https", sslsf)
                .build();


        PoolingHttpClientConnectionManager cm = null;
        cm = new PoolingHttpClientConnectionManager(sfr);
        cm.setMaxTotal(10000);
        cm.setDefaultMaxPerRoute(10000);



        // 请求配置
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(5000)
                .setConnectTimeout(5000)
                .setSocketTimeout(5000)
                .build();

        client = HttpClients.custom()
                .setSSLSocketFactory(sslsf)
                .setDefaultRequestConfig(requestConfig)
                .build();

    }

    public static SSLConnectionSocketFactory getSSLConnectsf()
            throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException, UnrecoverableKeyException {

        //String CLIENT_KEY_STORE = "client.keystore";// 客户端自己的证书；用于存储证书和公钥            连程序用的
        //String CLIENT_KEY_STORE_PWD = "123456";
        String CLIENT_TRUST_KEY_STORE = "D:/client.p12";//对端给的证书，用于存储可信任的证书
        String CLIENT_TRUST_KEY_STORE_PWD = "123456";

        KeyStore trustKeyStore = KeyStore.getInstance("PKCS12");
        FileInputStream trustStoreInput = new FileInputStream(new File(CLIENT_TRUST_KEY_STORE));
        trustKeyStore.load(trustStoreInput, CLIENT_TRUST_KEY_STORE_PWD.toCharArray());
        trustStoreInput.close();

        //需要双向认证时，此处才需要
        //KeyStore clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        //FileInputStream clientStoreInput = new FileInputStream(new File(CLIENT_KEY_STORE));
        //clientKeyStore.load(clientStoreInput, CLIENT_KEY_STORE_PWD.toCharArray());
        //clientStoreInput.close();

        SSLContext ctx = SSLContexts.custom()
                .loadTrustMaterial(trustKeyStore, new TrustSelfSignedStrategy())
                //.loadKeyMaterial(clientKeyStore, CLIENT_KEY_STORE_PWD.toCharArray())//双向认证时。此处才需要
                .build();

        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(ctx, new String[]{"TLSv1.2"},
                null,new AllowAllHostnameVerifier());
        return sslsf;
    }
}
